package com.carlinfo.common.dao.impl;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.carlinfo.common.dao.IBaseDao;
import com.carlinfo.common.util.DbUtil;
import com.carlinfo.common.util.PageInfoUtil;

public abstract class BaseDaoImpl<T> implements IBaseDao<T>
{
	protected Logger logger = LogManager.getLogger();
	
	protected DbUtil dbUtil = DbUtil.getInstance();
	
	protected Object baseObj;
	
	protected T findONeJDBC(String sql,List<Object> list)
	{
		
		Connection conn = null;
		PreparedStatement pst = null;
		ResultSet rs = null;
		try
		{
			logger.info("---{}---{}",sql,list);
			conn = dbUtil.getConnection();
			pst = conn.prepareStatement(sql);
			for (int i = 0; i < list.size(); i++)
			{
				pst.setObject(i+1, list.get(i));
			}
			rs = pst.executeQuery();
			if(rs.next())
			{
				T t = convertFromDb(rs);
				return t;
			}
		} catch (SQLException e)
		{
			e.printStackTrace();
		} finally
		{
			dbUtil.closeAll(rs, pst, conn);
		}
		return null;	
	}
	
	/**
	 * 查询多条带分页
	 * @param pageInfoUtil
	 * @param sql
	 * @param list
	 * @return
	 */
	protected List<T> findListByPage(PageInfoUtil pageInfoUtil,String sql,List<Object> list)
	{
		Connection conn = dbUtil.getConnection();
		PreparedStatement pst = null;
		ResultSet rs= null;
		try
		{	
			/**
			 * 当pageInfo不是空的时候,执行这个语句
			 */
			if(pageInfoUtil!=null)
			{
				String fromIndex = "from";
				String countSql = "select count(*) "+sql.substring(sql.indexOf(fromIndex), sql.length());
				this.logger.info("countSql===={}=={}",countSql,list);
				pst = conn.prepareStatement(countSql);
				for (int i = 0; i < list.size(); i++)
				{
					pst.setObject(i+1, list.get(i));
				}
				rs = pst.executeQuery();
				if(rs.next())
				{
					int totalRecord = rs.getInt(1);
					/**
					 * 务必先设置值,后面再取值,防止取出来的数据有误
					 */
					pageInfoUtil.setTotalRecord(totalRecord);
				}
				/**
				 * 运行完第一条语句,resultSet和pst关闭,conn不用关闭,可以重复使用
				 */
				rs.close();
				pst.close();
				sql = sql +" limit ?,?;";
//				System.out.println("我是谁");
				
				this.logger.info("sql==={},{}",sql,pageInfoUtil.toJSON());
				
				/**
				 * 将pageINfo中的值取出,下一步给sql中的?赋值
				 */
				list.add(pageInfoUtil.getCurrentRecord());
				list.add(pageInfoUtil.getPageSize());		
			}	
			return this.findList(sql, list);
		} catch (SQLException e)
		{
			e.printStackTrace();
		}finally
		{
			dbUtil.closeAll(rs, pst, conn);
		}
		return Collections.EMPTY_LIST;
	}
	
	/**
	 * 查询多条不分页
	 * @param sql
	 * @param list
	 * @return
	 */
	protected List<T> findList(String sql,List<Object> list)
	{
		List<T> resultList = new ArrayList<T>();
		Connection conn = dbUtil.getConnection();
		PreparedStatement pst = null;
		ResultSet rs= null;
		try
		{	
			pst= conn.prepareStatement(sql);
			/* 将list中的数据取出来,逐个给sql语句赋值 */
			for (int i = 0; i < list.size(); i++)
			{
				pst.setObject(i+1, list.get(i));
			}
			rs = pst.executeQuery();
			while(rs.next())
			{
				/**
				 * 调用封装好的方法将朝代逐个加到list中,用于方法的返回值
				 */
				T t = convertFromDb(rs);
				resultList.add(t);
			}
			return resultList;
		} catch (SQLException e)
		{
			e.printStackTrace();
		}finally
		{
			dbUtil.closeAll(rs, pst, conn);
		}
		return Collections.EMPTY_LIST;
	}
	
	public int excJDBC(String sql,List<Object> list)
	{
		Connection conn = null;
		PreparedStatement pst =null;
		int res = 0;
		try
		{
			conn = this.dbUtil.getConnection();
			pst = conn.prepareStatement(sql);
			for (int i = 0; i < list.size(); i++)
			{
				pst.setObject(i+1, list.get(i));
			}
			res = pst.executeUpdate();	
		} catch (SQLException e)
		{
			e.printStackTrace();
		}finally
		{
			dbUtil.closeAll(null, pst, conn);
		}
		return res;
	}
	
	public int excJDBC(String sql,List<Object> list,Map<String, Object> condMap)
	{
		Connection conn = null;
		PreparedStatement pst =null;
		ResultSet rs = null;
		int res = 0;
		try
		{
			conn = this.dbUtil.getConnection();
			pst = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
			for (int i = 0; i < list.size(); i++)
			{
				pst.setObject(i+1, list.get(i));
			}
			res = pst.executeUpdate();	
			rs = pst.getGeneratedKeys();
			if(rs.next())
			{
				condMap.put("id", rs.getObject(1));
			}
		} catch (SQLException e)
		{
			e.printStackTrace();
		}finally
		{
			dbUtil.closeAll(null, pst, conn);
		}
		return res;
	}
	/**
	 * 父类里面定义,谁重写就调用谁的方法
	 * @param rs
	 * @return
	 * @throws SQLException
	 */
	protected T convertFromDb(ResultSet rs) throws SQLException
	{
		try
		{
			Class cla = baseObj.getClass();
			T t = (T) cla.newInstance();
			Field[] fields = cla.getDeclaredFields();
			for (Field field : fields)
			{
				try
				{
				String fieldName = field.getName();
				/**
				 * 数据库中没有的类型就不赋值
				 */
				
				if(String.class.getName().equalsIgnoreCase(field.getType().getName())
						|| Date.class.getName().equalsIgnoreCase(field.getType().getName())
						||"byte".equalsIgnoreCase(field.getType().getName())
						||"int".equalsIgnoreCase(field.getType().getName())
						||"double".equalsIgnoreCase(field.getType().getName())
						|| "boolean".equalsIgnoreCase(field.getType().getName()))
				{
					if(field.getName().endsWith("Str"))
					{
						continue;
					}
				}else
				{
					continue;
				}
				String setName = "set"+fieldName.substring(0, 1).toUpperCase()+fieldName.substring(1,fieldName.length());
				Object val = rs.getObject(fieldName);
			
				if("byte".equalsIgnoreCase(field.getType().getName()))
				{
					val = Byte.valueOf(val+"");
				}
				if("double".equalsIgnoreCase(field.getType().getName()))
				{
					val = Double.valueOf(val+"");
				}
				if("boolean".equalsIgnoreCase(field.getType().getName()))
				{
					val = Byte.valueOf(val+"")==1 ? true : false;
				}
				Method method = cla.getMethod(setName, field.getType());
				method.invoke(t, val);
				}catch (Exception e) 
				{
//					System.out.println("字段名:"+field.getName());
//					this.logger.error("读取数据库失败了啊");
				}
			}
			return t;
		} catch (InstantiationException e)
		{
			e.printStackTrace();
		} catch (IllegalAccessException e)
		{
			e.printStackTrace();
		} catch (SecurityException e)
		{
			e.printStackTrace();
		} catch (IllegalArgumentException e)
		{
			e.printStackTrace();
		}
		return null;		
	}
}
